package com.example.demo.security.admin.aspectj;

import cn.hutool.core.util.ObjectUtil;
import com.example.demo.context.SysContext;
import com.example.demo.exception.TokenException;
import com.example.demo.util.JwtUtil;
import com.example.demo.util.RedisUtil;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

@Aspect
@Component
@Order(1)
public class AnonymousAspect {

    @Resource
    private RedisUtil redisUtil;

    /**
     * 免登陆校验
     *
     * @param joinPoint
     * @return
     * @throws Throwable
     * @description 切面将作用于所有标注了@RestController注解的类的所有方法，但排除了那些标注了NoNeedLogin注解的方法。
     */
    @Around("@within(org.springframework.web.bind.annotation.RestController) && execution(* *(..)) && !@annotation(com.example.demo.annoation.Anonymous)")
    public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取request对象
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        boolean checkToken = checkToken(request);
        return joinPoint.proceed(); // 继续执行原方法
    }

    public boolean checkToken(HttpServletRequest request) {
        // step1判断token是否存在
        String token = request.getHeader("admin-token");
        if (ObjectUtil.isNull(token) || token.isBlank() || redisUtil.get(token) == null) {
            SysContext.clean();
            throw new TokenException("token不存在或已过期");
        } else {
            // 判断token是否合法
            boolean verifiedToken = JwtUtil.verifyToken(token);
            if (!verifiedToken) {
                SysContext.clean();
                throw new TokenException("token不存在或已过期");
            } else {
                Object userId = JwtUtil.getPayload(token, "userId");
                SysContext.set(userId.toString());
                return true;
            }
        }
    }
}
